<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>

  <body>
    <!-- 
    call 调用 caller调用者 callee被调用者 employ雇佣 employer雇主 employee雇员
    apply应用 application应用程序
     -->
    <script>
      // 改变 this 指向
      // 是强行改变，不管你本身指向谁，我说你指向谁你就指向谁

      /* 
        call 
        fn.call( thisArg, ...otherArgs )
        理论上接受无限参数
        第一个参数就是函数内部的 this 指向
        你的第一个参数传递谁，那么函数内部的 this 就指向谁
        从第二个参数开始，依次是向函数内部传递参数
        */

      // 函数定义
      function fn(a, b) {
        // 本身这里的 this 应该是指向 window
        // this.name => window.name

        // 如果我能让这个函数内部的 this 指向 obj
        // this.name => obj.name
        console.log("fn被调用了，fn called", a, b);
        console.log(this);
      }

      // 普通调用
      // fn(2,3)//空字符串 window.name有定义且为空字符串（但不是undefined）

      // 调用fn 并将this绑定为obj
      // const zhaoyun = {name:"赵云"}
      // fn.call(zhaoyun,"白马","长枪")

      /* 
        2. apply 应用
        fn.apply( thisArg, argArr )
        改变this指向的
        第一个参数： 就是你要改变的 this 指向
        第二个参数： 接受一个数组，数组中的每一项依次是给函数传递参数
        */
      // const sanye = { name: "环眼贼" };
      // fn.apply(sanye, ["黑人", "黑马"]);

      /*
        // 3. bind
        // 新函数 = fn.bind( thisArg )
        // call 和 apply 都会把函数立即执行了
        // bind 不会立即执行函数，而是返回一个新的函数给你，这个新的函数是一个被改变了 this 指向过的函数
         */
      const daerer = { name: "大耳儿" };

      //   给fn函数绑定this为大耳儿 返回一个绑定了this的新函数
      let newFn = fn.bind(daerer);
      newFn("糜夫人", "孙尚香");

      //   给fn函数绑定this为大耳儿 同时绑定入参a"双股剑" b"tears" 返回一个绑定了this和入参的新函数
      //   let newFn = fn.bind(daerer,"双股剑","tears")
      //   console.log(typeof(newFn));
      //   newFn()
    </script>
  </body>
</html>
